package cn.yangsen.simplebeanmanager.engine;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;

import lombok.Getter;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import cn.yangsen.simplebeanmanager.annotation.Actualize;
import cn.yangsen.simplebeanmanager.annotation.Rely;
import cn.yangsen.simplebeanmanager.annotation.TypeRealize;
import cn.yangsen.simplebeanmanager.annotation.作为一个超链接;
import cn.yangsen.simplebeanmanager.annotation.固定的;
import cn.yangsen.simplebeanmanager.annotation.级联;
import cn.yangsen.simplebeanmanager.annotation.限定范围;
import cn.yangsen.simplebeanmanager.bean.html.A;
import cn.yangsen.simplebeanmanager.bean.html.Br;
import cn.yangsen.simplebeanmanager.bean.html.Button;
import cn.yangsen.simplebeanmanager.bean.html.Checkbox;
import cn.yangsen.simplebeanmanager.bean.html.Div;
import cn.yangsen.simplebeanmanager.bean.html.Element;
import cn.yangsen.simplebeanmanager.bean.html.Hidden;
import cn.yangsen.simplebeanmanager.bean.html.Label;
import cn.yangsen.simplebeanmanager.bean.html.Option;
import cn.yangsen.simplebeanmanager.bean.html.Radio;
import cn.yangsen.simplebeanmanager.bean.html.Script;
import cn.yangsen.simplebeanmanager.bean.html.Select;
import cn.yangsen.simplebeanmanager.bean.html.Table;
import cn.yangsen.simplebeanmanager.bean.html.Td;
import cn.yangsen.simplebeanmanager.bean.html.Text;
import cn.yangsen.simplebeanmanager.bean.html.Textarea;
import cn.yangsen.simplebeanmanager.bean.html.Tr;
import cn.yangsen.simplebeanmanager.bean.html.itfc.SubmitAble;
import cn.yangsen.simplebeanmanager.tool.ReflectTool;

public class 编辑用表格生成器 extends 表格生成器
{
	/**
	 * 用来判断是否已经保存到数据库
	 */
	private boolean 当前对象含有ID = false;

	/**
	 * 用于组装提交值的name 例:
	 * 
	 * <pre>
	 * a.		表示 当前在处理对象a的属性
	 * a.b.		表示 当前在处理对象a的属性b的属性
	 * a.b[1]		表示 当前在处理对象a的集合属性b的属性
	 * </pre>
	 */
	private String 当前所在类名 = null;

	/**
	 * 0：非级联，1:管理方，2:被管理方
	 */
	private int 级联属性处理进度 = 0;

	private Iterable<?> 控制方所有可能的值;

	@Getter
	private List<Script> js脚本;

	@Override
	public Table 生成标题栏在左侧的表格(Class<?> 对象的类型)
	{
		当前所在类名 = StringUtils.uncapitalize(对象的类型.getSimpleName()) + ".";
		return super.生成标题栏在左侧的表格(对象的类型);
	}

	@Override
	protected Element[] 处理单个属性(Field 属性, Object 对象)
	{
		if (当前所在类名 == null)
		{
			当前所在类名 = StringUtils.uncapitalize(属性.getDeclaringClass().getSimpleName()) + ".";
		}
		Object[] 备份数据 = 当前信息备份();
		当前所在类名 = 当前所在类名 + 属性.getName();
		Element[] r = super.处理单个属性(属性, 对象);
		当前信息还原(备份数据);
		return r;
	}

	@Override
	protected Element[][] 处理级联属性(Field 属性, Object 对象, Set<Field> 已被级联处理的属性)
	{
		List<Element[]> 结果 = new LinkedList<>();

		级联属性处理进度 = 1;
		结果.add(处理单个属性(属性, 对象));
		级联属性处理进度 = 2;
		级联 级联 = 属性.getAnnotation(级联.class);
		if (级联 != null)
		{
			String 被控制的属性名 = 级联.control();
			Field 被控制属性 = ReflectTool.获取对象的属性(对象, 被控制的属性名);
			if (被控制属性 != null)
			{
				已被级联处理的属性.add(被控制属性);

				if (控制方所有可能的值 != null)
				{
					List<Element> 被控制方元素 = new ArrayList<>();
					Div 级联显示区域 = new Div();
					被控制方元素.add(级联显示区域);

					String js关键字 = 生成js用方法名(当前所在类名);
					级联显示区域.setId(js关键字);

					Object 控制方的已选值 = ReflectTool.获取对象的属性值(对象, 属性);
					Object 被控制方的已选值 = ReflectTool.获取对象的属性值(对象, 被控制属性);

					Select 默认下拉菜单 = new Select();
					默认下拉菜单.setName(当前所在类名 + 被控制的属性名);

					StringBuilder js = new StringBuilder();
					js.append("function ");
					js.append(js关键字);
					js.append("_cascade(obj) {var td = obj.parentNode;var div;while (td = td.nextSibling) {if(div != null)break;var cn = td.childNodes;for(var i=0; i<cn.length;i++){if (cn[i].nodeName == \"DIV\" && cn[i].id==\"");
					js.append(js关键字);
					js.append("\"){div = cn[i];break;}}}if(div != null){");
					for (Object 控制方的值 : 控制方所有可能的值)
					{
						if (控制方的值 != null)
						{
							Object 被控制方的值的可能范围 = null;
							String 方法名 = 级联.metion();
							Class<?> 所属类 = 属性.getDeclaringClass();
							if (级联.isLocalMetion())
							{
								被控制方的值的可能范围 = ReflectTool.执行方法(所属类, 对象, 方法名, 控制方的值);
							}
							else
							{
								被控制方的值的可能范围 = ReflectTool.执行方法(所属类, 控制方的值, 方法名);
							}
							if (被控制方的值的可能范围 != null)
							{
								String 获取关键字方法名 = 级联.key();
								String 获取显示值方法名 = 级联.show();

								if (被控制方的值的可能范围 instanceof Iterable)
								{
									ArrayList<Option> 选项集 = new ArrayList<>();
									boolean 选中 = 控制方的值.equals(控制方的已选值);
									for (Object obj : (Iterable<?>) 被控制方的值的可能范围)
									{
										Object 当前值对应的关键参数 = ReflectTool.执行方法(所属类, obj, 获取关键字方法名);
										Object 当前值对应的显示参数 = ReflectTool.执行方法(所属类, obj, 获取显示值方法名);
										Option 选项 = new Option();
										选项集.add(选项);

										if (当前值对应的关键参数 != null)
										{
											选项.setValue(当前值对应的关键参数.toString());
										}
										if (当前值对应的显示参数 != null)
										{
											选项.setContent(当前值对应的显示参数.toString());
										}

										if (选中)
										{
											if (当前值对应的关键参数.equals(被控制方的已选值))
											{
												选项.setSelected("Selected");
											}
										}
									}
									if (默认下拉菜单.isEmpty() || 选中)
									{
										默认下拉菜单.clean();
										for (Option option : 选项集)
										{
											默认下拉菜单.add(option);
										}
									}

									// 将下拉列表生成js
									js.append("if (obj.value == \"");

									// TODO 这里应该有问题，未测试
									限定范围 范围 = 属性.getAnnotation(限定范围.class);
									js.append(获取限定范围时传递关键字(范围, 控制方的值));
									js.append("\"){");
									js.append("var chils= div.childNodes;var select;for(var i=0;i<chils.length;i++){if(chils[i].nodeName==\"SELECT\"){select=chils[i];break;}}select.innerHTML=\"");
									for (Option option : 选项集)
									{
										js.append(option.toHtml().replace("\"", "'"));
									}

									js.append("\";} else ");
								}
							}
						}
					}
					js.append("{div.innerHTML = \"\";}}}");
					添加脚本内容(js.toString());

					级联显示区域.add(默认下拉菜单);

					结果.add(被控制方元素.toArray(new Element[被控制方元素.size()]));
				}
			}
		}
		级联属性处理进度 = 0;
		return 结果.toArray(new Element[2][]);
	}

	@Override
	protected Element[] 处理Abstract属性值(Field 属性, Object 值)
	{
		ArrayList<Element> list = new ArrayList<>();

		Label 文本 = new Label();
		文本.setContent("实现");
		list.add(文本);

		Actualize 实现申明 = 属性.getType().getAnnotation(Actualize.class);
		if (实现申明 == null)
		{
			return null;
		}
		Class<?>[] 实现类集合 = 实现申明.value();

		String 唯一名称 = 生成js用方法名(当前所在类名);

		int i = 0;

		Div 实现类所在的块 = new Div();
		实现类所在的块.setId(唯一名称);

		for (Class<?> 实现类 : 实现类集合)
		{
			Radio 单选框 = new Radio();
			单选框.setName(当前所在类名);
			单选框.setOnclick(唯一名称 + "_switch" + i + "()");
			单选框.setValue(实现类.getSimpleName());
			list.add(单选框);

			Label 单选框内容 = new Label();
			Entity 实体 = 实现类.getAnnotation(Entity.class);
			if (实体 != null && StringUtils.isNoneEmpty(实体.name()))
			{
				单选框内容.setContent(实体.name());
			}
			else
			{
				单选框内容.setContent(实现类.getSimpleName());
			}
			list.add(单选框内容);

			Table js块 = null;
			Object[] 备份数据 = 当前信息备份();
			当前所在类名 = 当前所在类名 + ".";
			if (实现类.isInstance(值))
			{
				单选框.setChecked(true);
				ArrayList<Object> tempList = new ArrayList<>(1);
				tempList.add(值);
				js块 = 生成标题栏在左侧的表格(实现类, tempList);
				实现类所在的块.add(js块);
			}
			else
			{
				js块 = 生成标题栏在左侧的表格(实现类, null);
			}
			当前信息还原(备份数据);

			String js = "";
			if (js块 != null)
			{
				js = js块.toHtml();
				js = js.replace("\"", "'");
			}

			js = "function " + 唯一名称 + "_switch" + i + "(){" + 唯一名称 + ".innerHTML = \"" + js + "\";}";
			添加脚本内容(js);
			i++;
		}

		list.add(实现类所在的块);

		return list.toArray(new Element[list.size()]);
	}

	@Override
	protected Element[] 处理AsA注解的属性值(Object 对象, Field 属性)
	{
		Element[] 结果 = new Element[2];
		Object 值 = ReflectTool.获取对象的属性值(对象, 属性);
		if (值 != null)
		{
			Object id = ReflectTool.执行方法(值, "getId");
			作为一个超链接 超链接 = 属性.getAnnotation(作为一个超链接.class);
			if (超链接 != null)
			{
				A a = 根据注解组装超链接(超链接, 值);
				结果[0] = a;
			}
			if (id != null)
			{
				结果[1] = new Hidden(当前所在类名 + 属性.getName() + ".id", id.toString());
			}
		}
		return 结果;
	}

	@Override
	protected Element[] 处理Boolean属性值(Field 属性, Boolean 值)
	{
		Element[] 结果 = new Element[1];
		Checkbox 复选框 = new Checkbox();
		复选框.setDisabled(当前属性不可修改(属性));
		结果[0] = 复选框;
		复选框.setName(当前所在类名);
		if (值 != null)
		{
			boolean 真实值 = false;
			if (!值.getClass().isPrimitive())
			{
				真实值 = (Boolean) 值;
			}
			复选框.setChecked(真实值);
		}
		return 结果;
	}

	@Override
	protected Element[] 处理Entity注解的属性值(Field 属性, Object 值)
	{
		Element[] 结果 = new Element[1];
		当前所在类名 = 当前所在类名 + ".";
		if (值 == null)
		{
			结果[0] = 生成标题栏在左侧的表格(属性.getType(), null);
		}
		else
		{
			ArrayList<Object> list = new ArrayList<>(1);
			list.add(值);
			结果[0] = 生成标题栏在左侧的表格(属性.getType(), list);
		}

		return 结果;
	}

	@Override
	protected Element[] 处理Enum属性值(Field 属性, Object 值)
	{
		ArrayList<Element> 结果 = new ArrayList<>();

		Enum<?>[] all = (Enum<?>[]) 属性.getType().getEnumConstants();
		if (all != null)
		{
			Select 下拉列表 = new Select();
			下拉列表.setDisabled(当前属性不可修改(属性));
			下拉列表.setName(当前所在类名);
			结果.add(下拉列表);

			StringBuilder js = new StringBuilder();

			for (Enum<?> tempEnum : all)
			{
				Option 选项 = new Option();
				选项.setValue(tempEnum.name());
				TypeRealize tr = ReflectTool.获取枚举的注解(TypeRealize.class, tempEnum);

				Table 枚举实现类表格 = null;
				Hidden 格式类型 = null;
				String 格式类型名 = null;
				if (tempEnum.equals(值))
				{
					选项.setSelected("selected");
				}

				if (tr != null)
				{
					if (枚举实现类表格 == null)
					{
						Class<?> 实现类 = tr.value();

						Field[] 父类所有属性 = ReflectTool.获取类父类所有属性(实现类);
						ArrayList<Object> tempList = null;
						if (tempEnum.equals(值))
						{
							tempList = new ArrayList<>();
							tempList.add(值);
						}
						Object[] 备份数据 = 当前信息备份();
						当前所在类名 = 当前所在类名.substring(0, 当前所在类名.lastIndexOf(".") + 1);

						格式类型名 = 当前所在类名.substring(0, 当前所在类名.length() - 1);
						格式类型 = new Hidden(格式类型名, 实现类.getSimpleName());
						枚举实现类表格 = 生成标题栏在左侧的表格(实现类, tempList, 父类所有属性);
						当前信息还原(备份数据);
					}
					if (枚举实现类表格 != null)
					{
						js.append("if (obj.value == \"");
						js.append(tempEnum.name());
						js.append("\"){");
						js.append("div.innerHTML=\"");
						js.append((格式类型.toHtml() + 枚举实现类表格.toHtml()).replace("\"", "'").replace(格式类型名,
								格式类型名.subSequence(0, 格式类型名.lastIndexOf("[") + 1) + "\"+(ptb.rowIndex-1)+\"]"));
						js.append("\";} else ");
					}
				}

				选项.setContent(获取枚举的描述(tempEnum));
				下拉列表.add(选项);
			}
			if (js.length() > 0)
			{
				String 唯一名称 = 生成js用方法名(当前所在类名);

				Div div = new Div();
				div.setId(唯一名称);
				结果.add(div);

				下拉列表.addOnchange(唯一名称 + "_realizeh(this)");

				StringBuilder sb = new StringBuilder();
				sb.append("function ");
				sb.append(唯一名称);
				sb.append("_realizeh(obj)" + "{var ptb = obj;" + "var pptb;"
						+ "while(pptb = ptb.parentNode.parentNode)" + "{if(pptb.id===\"");
				sb.append(生成js用方法名(当前所在类名.substring(0, 当前所在类名.lastIndexOf("["))));
				sb.append("\")break;ptb = ptb.parentNode}" + "var div = obj;" + "while (div = div.nextSibling) "
						+ "{if (div.id === \"");
				sb.append(唯一名称);
				sb.append("\")break;}");
				sb.append(js.toString());
				sb.append("{div.innerHTML = \"\";}}");

				添加脚本内容(sb.toString());
			}
		}
		return 结果.toArray(new Element[结果.size()]);
	}

	@Override
	protected Element[] 处理Id注解的属性值(Object 对象, Field 属性)
	{
		Element[] 结果 = new Element[2];
		Object 值 = ReflectTool.获取对象的属性值(对象, 属性);
		if (值 != null)
		{
			当前对象含有ID = true;
			结果[0] = new Hidden(当前所在类名, 值.toString());
			结果[1] = new Label(值.toString());
		}
		else
		{
			当前对象含有ID = false;
		}
		return 结果;
	}

	@Override
	protected Element[] 处理Int属性值(Field 属性, Integer 值)
	{
		Element[] 结果 = new Element[1];
		Text 输入文本框 = new Text();
		输入文本框.setDisabled(当前属性不可修改(属性));
		结果[0] = 输入文本框;
		输入文本框.setName(当前所在类名);
		if (值 != null)
		{
			输入文本框.setValue(Integer.toString(值));
		}
		return 结果;
	}

	@Override
	protected Element[] 处理Long属性值(Field 属性, Long 值)
	{
		Element[] 结果 = new Element[1];
		Text 输入文本框 = new Text();
		输入文本框.setDisabled(当前属性不可修改(属性));
		结果[0] = 输入文本框;
		输入文本框.setName(当前所在类名);
		if (值 != null)
		{
			输入文本框.setValue(Long.toString(值));
		}
		return 结果;
	}

	@Override
	protected Element[] 处理Float属性值(Field 属性, Float 值)
	{
		Element[] 结果 = new Element[1];
		Text 输入文本框 = new Text();
		输入文本框.setSize(10);
		输入文本框.setDisabled(当前属性不可修改(属性));
		结果[0] = 输入文本框;
		输入文本框.setName(当前所在类名);
		if (值 != null)
		{
			输入文本框.setValue(Float.toString(值));
		}
		return 结果;
	}

	@Override
	protected Element[] 处理日期属性值(Field 属性, Date 值)
	{
		Element[] 结果 = new Element[1];
		Text 输入文本框 = new Text();
		输入文本框.setDisabled(当前属性不可修改(属性));
		结果[0] = 输入文本框;
		输入文本框.setName(当前所在类名);
		if (值 != null)
		{
			Calendar c = Calendar.getInstance();
			c.setTime(值);
			输入文本框.setValue(c.get(Calendar.YEAR) + "-" + c.get(Calendar.MONTH) + "-" + c.get(Calendar.DAY_OF_MONTH));
		}
		输入文本框.setOnClick("WdatePicker()");
		Script 脚本 = new Script();
		脚本.setType("text/javascript");
		脚本.setSrc("/js/WdatePicker.js");
		添加额外脚本(脚本);
		return 结果;
	}

	@Override
	protected <T> Element[] 处理Iterable属性值(Field 属性, Iterable<? extends T> 值, Class<? extends T> 实际类型)
	{
		Element[] 结果 = null;
		// TODO 此处其实应该判断是否是基本类型或封装类型
		// 每次修改此处还应对应修改另外一处
		if (实际类型 == Float.class || 实际类型 == String.class)
		{
			当前所在类名 = 当前所在类名 + "[n]";

			if (属性.isAnnotationPresent(固定的.class))
			{
				结果 = new Element[1];
				结果[0] = 生成标题栏在上方的简单对象表格(实际类型, 值);
			}
			else
			{
				结果 = 生成标题栏在上方的支持增加删除行的简单对象表格(实际类型, 值);
			}
		}
		else
		{
			当前所在类名 = 当前所在类名 + "[n].";

			if (属性.isAnnotationPresent(固定的.class))
			{
				结果 = new Element[1];
				结果[0] = 生成标题栏在上方的表格(实际类型, 值);
			}
			else
			{
				结果 = 生成标题栏在上方的支持增加删除行的表格(实际类型, 值);
			}
		}
		return 结果;
	}

	@Override
	protected Element[] 处理限定范围的简单属性值(Object 对象, Field 属性)
	{
		限定范围 范围 = 属性.getAnnotation(限定范围.class);
		if (范围 == null)
		{
			return null;
		}
		Class<?> 所属类 = 属性.getDeclaringClass();
		Object obj = ReflectTool.执行方法(所属类, 对象, 范围.获取的方法名());
		if (!(obj instanceof Iterable))
		{
			return null;
		}

		Object 值 = ReflectTool.获取对象的属性值(对象, 属性);
		Iterable<?> it = (Iterable<?>) obj;
		ArrayList<Element> 结果 = new ArrayList<>();

		Select 下拉列表 = new Select();

		if (级联属性处理进度 == 1)
		{
			下拉列表.addOnchange(生成js用方法名(当前所在类名) + "_cascade(this)");
			控制方所有可能的值 = it;
		}

		下拉列表.setDisabled(当前属性不可修改(属性));
		下拉列表.setName(当前所在类名 + "." + 范围.传递属性());
		结果.add(下拉列表);

		for (Object object : it)
		{
			Option 选项 = new Option();
			if (object.equals(值))
			{
				选项.setSelected("selected");
			}
			选项.setValue(获取限定范围时传递关键字(范围, object));
			选项.setContent(获取限定范围时显示内容(范围, object));
			下拉列表.add(选项);
		}
		return 结果.toArray(new Element[结果.size()]);
	}

	@Override
	protected Element[] 处理限定范围的Iterable属性值(Object 对象, Field 属性)
	{
		限定范围 范围 = 属性.getAnnotation(限定范围.class);
		if (范围 == null)
		{
			return null;
		}
		Object obj = ReflectTool.执行方法(属性.getDeclaringClass(), 对象, 范围.获取的方法名());
		if (!(obj instanceof Iterable))
		{
			return new Element[0];
		}

		Object 值 = ReflectTool.获取对象的属性值(对象, 属性);
		Iterable<?> it = (Iterable<?>) obj;
		ArrayList<Element> 结果 = new ArrayList<>();

		int i = 0;

		for (Object 单个可选对象 : it)
		{
			Checkbox 选项 = new Checkbox();
			结果.add(选项);
			if (值 != null)
			{
				for (Object 单个值 : (Iterable<?>) 值)
				{
					if (单个可选对象.equals(单个值))
					{
						选项.setChecked(true);
					}
				}
			}

			选项.setValue(获取限定范围时传递关键字(范围, 单个可选对象));
			选项.setName(当前所在类名 + "[" + i + "]." + 范围.传递属性());
			String 显示内容 = 获取限定范围时显示内容(范围, 单个可选对象);
			if (显示内容 != null)
			{
				结果.add(new Label(显示内容.toString()));
			}
			结果.add(new Br());
			i++;
		}

		return 结果.toArray(new Element[结果.size()]);
	}

	@Override
	protected Element[] 处理Rely注解的属性值(final Object 对象, Field 属性)
	{
		Rely rely = 属性.getAnnotation(Rely.class);
		String 目标 = rely.target();
		String[] 目标属性树 = 目标.split("\\.");
		Object 目标对象 = 对象;
		for (String 属性名 : 目标属性树)
		{
			if (目标对象 == null)
			{
				return null;
			}
			目标对象 = ReflectTool.获取对象的属性值(目标对象, 属性名);
		}
		if (目标对象 == null || !(目标对象 instanceof Enum<?>))
		{
			return null;
		}

		int i = ((Enum<?>) 目标对象).ordinal();
		Class<?> 实现类型 = rely.dstClass()[i];
		return 处理对象类型(对象, 属性, 实现类型);
	}

	@Override
	protected Element[] 处理String属性值(Field 属性, Object 值)
	{
		Element[] 结果 = new Element[1];

		Column column = 属性.getAnnotation(Column.class);
		if (column != null && (column.length() > 30 || column.columnDefinition().toUpperCase().indexOf("text") >= 0))
		{
			Textarea 文本区 = new Textarea();
			文本区.setDisabled(当前属性不可修改(属性));
			结果[0] = 文本区;
			文本区.setName(当前所在类名);
			if (值 != null)
			{
				文本区.setContent((String) 值);
			}
		}
		else
		{
			Text 输入文本框 = new Text();
			输入文本框.setDisabled(当前属性不可修改(属性));
			输入文本框.setName(当前所在类名);
			结果[0] = 输入文本框;
			if (值 != null)
			{
				输入文本框.setValue((String) 值);
			}
		}
		return 结果;
	}

	protected boolean 当前属性不可修改(Field 属性)
	{
		if (!当前对象含有ID)
		{
			return false;
		}
		Column col = 属性.getAnnotation(Column.class);
		if (col == null)
		{
			return false;
		}
		return !col.updatable();
	}

	@Override
	protected void 添加横向数据(Table 表格, Field[] 属性集合, Iterable<?> 对象集合)
	{
		if (当前所在类名.indexOf("[n].") > 0)
		{
			if (对象集合 != null)
			{
				int i = 0;
				for (Object 对象 : 对象集合)
				{
					将当前类名变为动态(i);
					添加横向单条数据(表格, 属性集合, 对象);
					i++;
				}
			}
		}
		else
		{
			super.添加横向数据(表格, 属性集合, 对象集合);
		}
	}

	protected void 添加脚本内容(String s)
	{
		Script scr = null;
		if (js脚本 == null)
		{
			js脚本 = new ArrayList<>();
			scr = new Script();
			js脚本.add(scr);
			scr.setType("text/javascript");
		}
		else
		{
			scr = js脚本.get(0);
		}
		scr.addContent(s);
	}

	protected void 添加额外脚本(Script scr)
	{
		if (js脚本 == null)
		{
			js脚本 = new ArrayList<>();
			Script s = new Script();
			js脚本.add(s);
			s.setType("text/javascript");
		}
		js脚本.add(scr);
	}

	@Override
	protected void 添加纵向数据(Table 表格, Field[] 属性集合, Iterable<?> 对象集合)
	{
		if (当前所在类名 != null && 当前所在类名.indexOf("[n].") > 0)
		{
			int i = 0;
			for (Object 对象 : 对象集合)
			{
				将当前类名变为动态(i);
				添加纵向单条数据(表格, 属性集合, 对象);
				i++;
			}
		}
		else
		{
			super.添加纵向数据(表格, 属性集合, 对象集合);
		}
	}

	public Element[] 生成标题栏在上方的支持增加删除行的简单对象表格(Class<?> 类型, Iterable<?> 值)
	{
		ArrayList<Element> 结果 = new ArrayList<>();
		ArrayList<Object> list = new ArrayList<>();
		if (值 != null)
		{
			值.forEach(list::add);
		}
		if (类型 == Float.class)
		{
			list.add(Float.valueOf(0));
		}
		else if (类型 == String.class)
		{
			list.add("");
		}

		Table t = 生成标题栏在上方的简单对象表格(类型, list);
		结果.add(t);
		添加增加删除行功能(t, 结果);
		return 结果.toArray(new Element[结果.size()]);
	}

	/**
	 * 格式：
	 * <table border="1">
	 * <tr>
	 * <td>属性1</td>
	 * <td>属性2</td>
	 * <td>属性3</td>
	 * <td>操作</td>
	 * </tr>
	 * <tr>
	 * <td>xxx</td>
	 * <td>xxx</td>
	 * <td>xxx</td>
	 * <td><input value="删除" type="button" onclick="表格内前缀_del(this)"/></td>
	 * </tr>
	 * <tr>
	 * <td>yyy</td>
	 * <td>yyy</td>
	 * <td>yyy</td>
	 * <td><input value="删除" type="button" onclick="表格内前缀_del(this)"/></td>
	 * </tr>
	 * </table>
	 * <input value="添加" type="button" onclick="表格内前缀_add()"/>
	 * 
	 * @return
	 */
	public Element[] 生成标题栏在上方的支持增加删除行的表格(Class<?> 类型, Iterable<?> 值)
	{
		ArrayList<Element> 结果 = new ArrayList<>();
		ArrayList<Object> list = new ArrayList<>();
		if (值 != null)
		{
			值.forEach(list::add);
		}
		Object 空实例 = null;
		if (list.size() > 0)
		{
			空实例 = 创建一个新实例(类型, list.get(list.size() - 1));
		}
		else
		{
			空实例 = 创建一个新实例(类型, null);
		}

		list.add(空实例);

		Table t = 生成标题栏在上方的表格(类型, list);
		结果.add(t);
		添加增加删除行功能(t, 结果);
		return 结果.toArray(new Element[结果.size()]);
	}

	private void 添加增加删除行功能(Table t, ArrayList<Element> 结果)
	{
		if (t == null)
		{
			return;
		}
		int begin = 当前所在类名.lastIndexOf("[");
		String 不包含序号的当前所在类名 = 当前所在类名.substring(0, begin);

		String js用的关键字 = 生成js用方法名(不包含序号的当前所在类名);

		t.setId(js用的关键字);
		Tr[] trs = t.getTrs();
		if (ArrayUtils.isNotEmpty(trs))
		{
			Td 操作列 = new Td();
			Label 操作文本区 = new Label();
			操作文本区.setContent("操作");
			操作列.add(操作文本区);
			trs[0].add(操作列);
		}

		for (int i = 1; i < trs.length; i++)
		{
			Tr tr = trs[i];
			Td 操作列 = new Td();
			tr.add(操作列);
			操作列.add(new Button("删除", js用的关键字 + "_del(this)"));
		}

		Tr js行 = trs[trs.length - 1];
		t.getElements().remove(js行);

		StringBuilder js脚本 = new StringBuilder();

		// 将js脚本中的编号变为动态值
		String tempS = js行.toHtml();
		tempS = tempS.replace(不包含序号的当前所在类名 + "[" + (trs.length - 2) + "]", 不包含序号的当前所在类名 + "['+(tb.rows.length -2)+']");

		int 方括号起始位置 = 不包含序号的当前所在类名.lastIndexOf("[");
		int 方括号结束位置 = 不包含序号的当前所在类名.lastIndexOf("]");
		String tempS2 = 不包含序号的当前所在类名;
		String 前置js = "";
		int 序列 = 0;
		while (方括号起始位置 > 0)
		{
			String tempS3 = tempS2.substring(0, 方括号起始位置);
			前置js = 前置js + "var ptb" + 序列 + " = tb;var pptb" + 序列 + ";while (pptb" + 序列 + " = ptb" + 序列
					+ ".parentNode.parentNode){if(pptb" + 序列 + ".id === \"" + 生成js用方法名(tempS3) + "\")break;ptb" + 序列
					+ "=ptb" + 序列 + ".parentNode;}";

			tempS = tempS.replace(tempS2, tempS3 + "['+(ptb" + 序列 + ".rowIndex -1)+'" + tempS2.substring(方括号结束位置));
			方括号起始位置 = tempS3.lastIndexOf("[");
			方括号结束位置 = tempS3.lastIndexOf("]");
			序列++;
		}

		js脚本.append("function ");
		js脚本.append(js用的关键字);
		js脚本.append("_add(tb){");
		js脚本.append(前置js);
		js脚本.append("while (tb = tb.previousSibling){if(tb.id === \"");
		js脚本.append(js用的关键字);
		js脚本.append("\"){var row = tb.insertRow(tb.rows.length);row.innerHTML = '");
		js脚本.append(tempS);
		js脚本.append("';break;}}}function ");
		js脚本.append(js用的关键字);
		js脚本.append("_del(obj) {var rowIndex = obj.parentNode.parentNode.rowIndex;var tb = document.getElementById(\"");
		js脚本.append(js用的关键字);
		js脚本.append("\");tb.deleteRow(rowIndex);for (var i = rowIndex ; i < ");
		js脚本.append("tb.rows.length");
		js脚本.append("; i++) {");

		// 提取所有会提交的值
		Collection<Element> allE = js行.getAllElements();
		for (Element e : allE)
		{
			if (e instanceof SubmitAble)
			{
				String name = ((SubmitAble) e).getName();
				if (StringUtils.isNotEmpty(name))
				{
					// 将全名截断
					// 如果全名为aaa.bbb[x].ccc[a].ddd，当前“不包含序号的当前所在类名”为aaa.bbb,则截取后.ccc[a].ddd
					int 起始位置 = name.indexOf("]", name.indexOf(不包含序号的当前所在类名) + 不包含序号的当前所在类名.length());
					name = name.substring(起始位置 + 1);
					js脚本.append("var one = document.getElementsByName(\"");
					js脚本.append(不包含序号的当前所在类名);
					js脚本.append("[\"+ i + \"]");

					js脚本.append(name);
					js脚本.append("\");if(one.length>0)one[0].setAttribute(\"name\",\"");
					js脚本.append(不包含序号的当前所在类名);
					js脚本.append("[\"+ (i - 1)+ \"]");
					js脚本.append(name);
					js脚本.append("\");");
				}
			}
		}

		// id特殊处理(因为ID不会出现在js行)
		js脚本.append("var one = document.getElementsByName(\"");
		js脚本.append(不包含序号的当前所在类名);
		js脚本.append("[\"+ i + \"].id\");if(one.length>0)one[0].setAttribute(\"name\",\"");
		js脚本.append(不包含序号的当前所在类名);
		js脚本.append("[\"+ (i - 1)+ \"].id\");}}");

		添加脚本内容(js脚本.toString());

		Button 添加按钮 = new Button();
		添加按钮.setValue("添加");
		添加按钮.setOnclick(js用的关键字 + "_add(this)");
		结果.add(添加按钮);

	}

	/**
	 * @param 类型
	 * @param 参考对象
	 *            可以为空
	 * @return
	 */
	private Object 创建一个新实例(Class<?> 类型, Object 参考对象)
	{
		Object 实例 = ReflectTool.构造一个新对象(类型);

		if (参考对象 != null)
		{
			// 提取所有必填属性
			Field[] fs = ReflectTool.获取类及其父类所有属性(类型);
			for (Field 属性 : fs)
			{
				ManyToOne mto = 属性.getAnnotation(ManyToOne.class);
				if (mto != null)
				{
					// 必填
					if (!mto.optional())
					{
						// 无范围限制，因为如果有范围限制且必填，则一般会采用级联注解(@Cascade)处理
						if (!属性.isAnnotationPresent(限定范围.class))
						{
							Object 值 = ReflectTool.获取对象的属性值(参考对象, 属性);
							ReflectTool.填充对象的属性值(实例, 属性, 值);
						}
					}
				}
			}
		}

		return 实例;
	}

	private Object[] 当前信息备份()
	{
		Object[] obj = new Object[2];
		obj[0] = 当前所在类名;
		obj[1] = 当前对象含有ID;
		return obj;
	}

	private void 当前信息还原(Object[] 备份数据)
	{
		当前所在类名 = (String) 备份数据[0];
		当前对象含有ID = (boolean) 备份数据[1];
	}

	private void 将当前类名变为动态(int i)
	{
		if (i == 0)
		{
			当前所在类名 = 当前所在类名.replace("[n]", "[" + i + "]");
		}
		else
		{
			int last = 当前所在类名.lastIndexOf("[" + (i - 1) + "]");
			String tempS = 当前所在类名.substring(last);
			tempS = tempS.replace("[" + (i - 1) + "]", "[" + i + "]");
			当前所在类名 = 当前所在类名.substring(0, last) + tempS;
		}
	}

	private Table 生成标题栏在左侧的表格(Class<?> 对象的类型, Iterable<?> 对象集合, Field... 临时不显示属性)
	{
		if (StringUtils.isEmpty(当前所在类名))
		{
			String 类型名 = 对象的类型.getSimpleName();
			当前所在类名 = StringUtils.uncapitalize(类型名) + ".";
		}
		if (对象的类型.getAnnotation(Entity.class) == null)
		{
			return null;
		}
		Field[] 属性集合 = ReflectTool.获取类及其父类所有属性(对象的类型);
		if (属性集合 == null)
		{
			return null;
		}

		if (不显示的属性 != null)
		{
			属性集合 = Arrays.asList(属性集合).stream().filter(f -> !不显示的属性.contains(f)).toArray(Field[]::new);
		}

		if (临时不显示属性 != null)
		{
			List<Field> 临时不显示属性列表 = Arrays.asList(临时不显示属性);
			属性集合 = Arrays.asList(属性集合).stream().filter(f -> !临时不显示属性列表.contains(f)).toArray(Field[]::new);
		}

		Table 表格 = new Table();
		// 表格.添加列(获取标题列());
		添加纵向数据(表格, 属性集合, 对象集合);

		if (表格 == null || 表格.isEmpty())
		{
			return null;
		}
		return 表格;
	}

	private String 生成js用方法名(String 原值)
	{
		原值 = 原值.replace(".", "_");
		原值 = 原值.replace("[", "");
		return 原值.replace("]", "");
	}

	@Override
	protected Element[][] 处理简单对象集合(Iterable<?> 对象集合)
	{
		if (对象集合 == null)
		{
			return null;
		}
		ArrayList<Element[]> list = new ArrayList<>();
		int i = 0;
		for (Object object : 对象集合)
		{
			将当前类名变为动态(i);
			i++;
			Text 输入文本框 = new Text();
			输入文本框.setName(当前所在类名);
			输入文本框.setValue(object.toString());
			list.add(new Element[]
				{ 输入文本框 });
		}
		return list.toArray(new Element[list.size()][]);
	}
}
